﻿/*
// Exepack.NET 
// http://www.codeplex.com/exepack
//
// Compression options
// Written by Y [24-01-10]
// Copyright (c) 2008-2010 Alexey Yakovlev
*/

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.ComponentModel;

namespace Exepack
{
	/// <summary>
	/// Defines compression options for ExeCompressor class
	/// </summary>
	public class CompressionOptions
	{
		private CompressionOptions()
		{
			MainAssembly = null;
			AdditionalAssemblies = new List<AssemblyInformation>();

			// defailt settings
			CopyIcons = true;
			CopyVersionInfo = true;
		}

		/// <summary>
		/// Creates CompressionOptions for executable image
		/// </summary>
		public static CompressionOptions Create(string exeName)
		{
			var opt = new CompressionOptions();
			opt.MainAssembly = new AssemblyInformation(exeName);

			foreach (var refAsm in opt.MainAssembly.AllReferences)
				opt.AdditionalAssemblies.Add(refAsm);

			return opt;
		}

		private AssemblyInformation mainAsm;

		/// <summary>
		/// Executable file to be compressed
		/// </summary>
		[Browsable(false)]
		public AssemblyInformation MainAssembly
		{
			get { return mainAsm; }
			set
			{
				mainAsm = value;
				
				if (mainAsm == null)
				{
					OutputAssemblyName = OutputFileName = null;
					return;
				}

				OutputAssemblyName = mainAsm.AsmName.Name + "Loader";
				OutputFileName = Path.ChangeExtension(MainAssembly.FileName, "packed.exe");
			}
		}

		/// <summary>
		/// Additional assemblies to be compressed along with MainAssembly
		/// This list typically contains assemblies statically referenced by MainAssembly
		/// </summary>
		[Browsable(false)]
		public IList<AssemblyInformation> AdditionalAssemblies { get; private set; }

		/// <summary>
		/// Adds single assembly to the list of additional assemblies
		/// </summary>
		public void Add(string fileName)
		{
			var ass = new AssemblyInformation(fileName);

			// add if not already added
			if (!AdditionalAssemblies.Any(v => v.FullName == ass.FullName))
				AdditionalAssemblies.Add(ass);
		}

		/// <summary>
		/// Adds assembly and all its references to the list of additional assemblies
		/// </summary>
		public void AddRecursive(string fileName)
		{
			var ass = new AssemblyInformation(fileName);

			if (!AdditionalAssemblies.Any(v => v.FullName == ass.FullName))
				AdditionalAssemblies.Add(ass);

			// add referenced assemblies that are not already added
			foreach (var asm in ass.AllReferences.Where(a => !AdditionalAssemblies.Any(v => v.FullName == a.FullName)))
				AdditionalAssemblies.Add(asm);
		}
		
		/// <summary>
		/// Name of the output assembly
		/// </summary>
		public string OutputAssemblyName { get; set; }

		/// <summary>
		/// Name of the output file
		/// </summary>
		public string OutputFileName { get; set; }

		/// <summary>
		/// Set to true if ExeCompressor should copy Win32 icons from the source assembly
		/// </summary>
		public bool CopyIcons { get; set; }

		/// <summary>
		/// Set to true if ExeCompressor should copy Win32 version info from the source assembly
		/// </summary>
		public bool CopyVersionInfo { get; set; }

		/// <summary>
		/// Returns uncompressed size of all assemblies
		/// </summary>
		[Browsable(false)]
		public int UncompressedSize
		{
			get
			{
				int size = AdditionalAssemblies.Where(a => a.IsILOnly && !a.IsSystemAssembly).Sum(a => a.FileSize);

				if (MainAssembly != null)
					size += MainAssembly.FileSize;

				return size;
			}
		}
	}
}
